<template>
  <view class="drag-sort-container">
    <view class="drag-list">
      <!-- 插入位置提示条 -->
      <view 
        class="insert-indicator" 
        v-if="showIndicator && draggingIndex !== -1"
        :style="{ 
          top: indicatorPosition + 'px',
          transition: 'top 0.2s ease'
        }"
      ></view>
      
      <!-- 拖拽项列表 -->
      <view
        v-for="(item, index) in list"
        :key="item.id"
        class="drag-item-wrapper"
        :style="{
          transform: getItemTransform(index),
          transition: draggingIndex === -1 ? 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)' : 'none',
          zIndex: draggingIndex === index ? 999 : 1
        }"
      >
        <view
          class="drag-item"
          :class="{ 'is-dragging': draggingIndex === index }"
          @touchstart="handleTouchStart(index, $event)"
          @touchmove.stop.prevent="handleTouchMove"
          @touchend="handleTouchEnd"
          @touchcancel="handleTouchEnd"
        >
          <view class="drag-handle">⋮⋮</view>
          <text class="drag-text">{{ item.name }}</text>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'IndicatorDragSort',
  data() {
    return {
      list: [
        { id: 1, name: '项目1' },
        { id: 2, name: '项目2' },
        { id: 3, name: '项目3' },
        { id: 4, name: '项目4' },
        { id: 5, name: '项目5' }
      ],
      draggingIndex: -1,           // 当前拖拽项索引
      targetIndex: -1,             // 目标插入位置索引
      startY: 0,                   // 开始触摸Y坐标
      offsetY: 0,                  // 当前偏移量
      itemHeight: 110,             // 单项高度(px)
      longPressTimer: null,        // 长按定时器
      isLongPressed: false,        // 是否触发长按
      showIndicator: false,        // 是否显示插入指示器
      indicatorPosition: 0,        // 指示器位置
      itemPositions: []            // 每项的顶部位置
    }
  },
  
  mounted() {
    this.calculateItemPositions()
    
    // 监听屏幕尺寸变化
    if (uni.onWindowResize) {
      uni.onWindowResize(() => {
        this.calculateItemPositions()
      })
    }
  },
  
  beforeDestroy() {
    if (uni.offWindowResize) {
      uni.offWindowResize()
    }
  },
  
  methods: {
    // 计算每项的位置
    calculateItemPositions() {
      const query = uni.createSelectorQuery().in(this)
      query.selectAll('.drag-item').boundingClientRect((rects) => {
        if (rects && rects.length > 0) {
          this.itemPositions = rects.map(rect => ({
            top: rect.top,
            height: rect.height
          }))
        }
      }).exec()
    },
    
    // 触摸开始
    handleTouchStart(index, e) {
      this.isLongPressed = false
      this.longPressTimer = setTimeout(() => {
        this.isLongPressed = true
        this.startDrag(index, e.touches[0])
      }, 300)
    },
    
    // 开始拖拽
    startDrag(index, touch) {
      this.draggingIndex = index
      this.targetIndex = index
      this.startY = touch.clientY
      this.offsetY = 0
      this.showIndicator = true
      
      // 重新计算位置
      this.$nextTick(() => {
        this.calculateItemPositions()
        // 初始化指示器位置
        this.updateIndicatorPosition()
      })
    },
    
    // 触摸移动
    handleTouchMove(e) {
      if (this.draggingIndex === -1 || !this.isLongPressed) return
      
      const touch = e.touches[0]
      this.offsetY = touch.clientY - this.startY
      
      // 计算目标插入位置
      this.calculateTargetPosition(touch.clientY)
      
      // 更新指示器位置
      this.updateIndicatorPosition()
    },
    
    // 计算目标插入位置
    calculateTargetPosition(currentY) {
      const dragItemTop = this.itemPositions[this.draggingIndex].top + this.offsetY
      const dragItemBottom = dragItemTop + this.itemHeight
      const dragItemCenter = dragItemTop + this.itemHeight / 2
      
      // 默认插入到当前位置
      let newTargetIndex = this.draggingIndex
      
      // 检查是否应该插入到其他位置
      for (let i = 0; i < this.itemPositions.length; i++) {
        const itemTop = this.itemPositions[i].top
        const itemBottom = itemTop + this.itemHeight
        const itemCenter = itemTop + this.itemHeight / 2
        
        // 如果拖拽项中心在某个项的上半部分，插入到该项之前
        if (dragItemCenter < itemCenter && dragItemBottom > itemTop) {
          newTargetIndex = i
          break
        }
        
        // 如果拖拽项中心在某个项的下半部分，插入到该项之后
        if (dragItemCenter > itemCenter && dragItemTop < itemBottom) {
          newTargetIndex = i + 1
        }
      }
      
      // 限制范围
      newTargetIndex = Math.max(0, Math.min(this.list.length, newTargetIndex))
      
      if (newTargetIndex !== this.targetIndex) {
        this.targetIndex = newTargetIndex
      }
    },
    
    // 更新指示器位置
    updateIndicatorPosition() {
      if (this.targetIndex >= this.itemPositions.length) {
        // 插入到最后
        const lastItem = this.itemPositions[this.itemPositions.length - 1]
        this.indicatorPosition = lastItem.top + this.itemHeight
      } else if (this.targetIndex < this.itemPositions.length) {
        // 插入到指定位置
        this.indicatorPosition = this.itemPositions[this.targetIndex].top
      }
    },
    
    // 获取变换样式
    getItemTransform(index) {
      if (this.draggingIndex === -1) {
        return '' // 非拖拽状态无变换
      }
      
      if (index === this.draggingIndex) {
        // 拖拽项跟随手指移动
        return `translateY(${this.offsetY}px)`
      } else if (index < this.draggingIndex && index >= this.targetIndex) {
        // 需要向下移动的项
        return `translateY(${this.itemHeight}px)`
      } else if (index > this.draggingIndex && index < this.targetIndex) {
        // 需要向上移动的项
        return `translateY(${-this.itemHeight}px)`
      }
      
      return '' // 其他项保持原位
    },
    
    // 触摸结束
    handleTouchEnd() {
      clearTimeout(this.longPressTimer)
      
      if (this.isLongPressed) {
        // 执行实际的数组重排
        if (this.draggingIndex !== this.targetIndex) {
          this.reorderList()
        }
        
        // 重置状态
        this.resetDragState()
      }
    },
    
    // 重新排序列表
    reorderList() {
      const fromIndex = this.draggingIndex
      const toIndex = this.targetIndex
      
      if (fromIndex === toIndex) return
      
      const newList = [...this.list]
      const [movedItem] = newList.splice(fromIndex, 1)
      
      // 调整插入索引
      const adjustedIndex = toIndex > fromIndex ? toIndex - 1 : toIndex
      newList.splice(adjustedIndex, 0, movedItem)
      
      this.list = newList
    },
    
    // 重置拖拽状态
    resetDragState() {
      this.draggingIndex = -1
      this.targetIndex = -1
      this.offsetY = 0
      this.isLongPressed = false
      this.showIndicator = false
      this.indicatorPosition = 0
      
      // 延迟重新计算位置，确保DOM更新完成
      setTimeout(() => {
        this.calculateItemPositions()
      }, 50)
    }
  }
}
</script>

<style scoped>
.drag-sort-container {
  padding: 20rpx;
  background-color: #f5f5f5;
  min-height: 100vh;
  position: relative;
}

.drag-list {
  position: relative;
}

.drag-item-wrapper {
  position: relative;
  margin-bottom: 20rpx;
}

.drag-item {
  display: flex;
  align-items: center;
  padding: 30rpx;
  background: #ffffff;
  border-radius: 16rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
}

.drag-item.is-dragging {
  background: #f8f9fa;
  box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.15);
  transform: scale(1.02);
}

.drag-handle {
  font-size: 36rpx;
  color: #c0c4cc;
  margin-right: 20rpx;
  touch-action: none;
}

.drag-text {
  flex: 1;
  font-size: 32rpx;
  color: #303133;
}

/* 插入位置指示器 */
.insert-indicator {
  position: fixed;
  left: 20rpx;
  right: 20rpx;
  height: 6rpx;
  background-color: #007aff;
  border-radius: 3rpx;
  z-index: 1000;
  pointer-events: none;
}

.insert-indicator::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 0;
  height: 0;
  border-top: 8rpx solid transparent;
  border-bottom: 8rpx solid transparent;
  border-left: 12rpx solid #007aff;
  transform: translateY(-50%);
}

.insert-indicator::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 0;
  width: 0;
  height: 0;
  border-top: 8rpx solid transparent;
  border-bottom: 8rpx solid transparent;
  border-right: 12rpx solid #007aff;
  transform: translateY(-50%);
}
</style>
